package com.hitqz.robot.camera;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONArray;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.google.common.collect.Table;
import com.hitqz.robot.api.business.enums.BrandEnum;
import com.hitqz.robot.camera.configure.EquipmentCmdEnum;
import com.hitqz.robot.camera.dto.*;
import com.hitqz.robot.camera.netty.PelcodMessage;
import com.hitqz.robot.camera.util.PelcodCacheUtil;
import com.hitqz.robot.camera.util.PelcodCameraToolkit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

/**
 * @author kehanjiang
 * @date 2024/08/15
 */
@Service("PelcodCameraService")
@Slf4j
public class PelcodCameraService implements IEquipmentService {

    private final Table<String, String, String> paramsCacheTable = HashBasedTable.create();


    @Override
    public BrandEnum brand() {
        return BrandEnum.PELCOD;
    }

    @Override
    public boolean intSdk() {
        return true;
    }

    @Override
    public boolean login(EquipmentLoginParamsDto dto) {
        return PelcodCameraToolkit.init(dto.getIp(), dto.getPort());
    }

    @Override
    public boolean loginout(String ip) {
        return IEquipmentService.super.loginout(ip);
    }

    @Override
    public boolean setEquipmentParams(QueryParamsDto dto, List<EquipmentParamsDto> paramsDtos, boolean async) {
        try {
            Optional<EquipmentParamsDto> panDto = paramsDtos.stream().filter(t -> "pan".equals(t.getKey())).findFirst();
            Optional<EquipmentParamsDto> tiltDto = paramsDtos.stream().filter(t -> "tilt".equals(t.getKey())).findFirst();
            if (panDto.isPresent() && tiltDto.isPresent()) {
                float pan = Float.parseFloat(panDto.get().getValue());
                float tilt = Float.parseFloat(tiltDto.get().getValue());
                PelcodCameraToolkit.setPtzPose(pan, tilt);
                if (async) {
                    //异步立刻返回
                    return true;
                }
                //同步-检测是否到位
                for (int i = 0; i < 10; i++) {
                    Thread.sleep(1000);
                    List<EquipmentParamsDto> params = this.getEquipmentParams(dto);
                    Optional<EquipmentParamsDto> currentPanDto = params.stream().filter(t -> "pan".equals(t.getKey())).findFirst();
                    Optional<EquipmentParamsDto> currentTiltDto = params.stream().filter(t -> "tilt".equals(t.getKey())).findFirst();
                    if (currentPanDto.isEmpty() || currentTiltDto.isEmpty()) {
                        continue;
                    }
                    float currentPan = Float.parseFloat(currentPanDto.get().getValue());
                    float currentTilt = Float.parseFloat(currentTiltDto.get().getValue());
                    if (Math.abs(currentPan-pan) < 1 && Math.abs(currentTilt-tilt) < 1){
                        log.info("[pelcod]到位");
                        break;
                    }
                    //外部中断标志
                    if (PelcodCacheUtil.getStopFlag()){
                        log.info("[pelcod]外部中断,退出到位判断循环");
                        break;
                    }
                }
            }
            return true;
        }catch (Exception e){
            log.error("[pelcod]set param error,{}",e.getMessage());
            return false;
        }
    }

    @Override
    public List<EquipmentParamsDto> getEquipmentParams(QueryParamsDto dto) {
        List<EquipmentParamsDto> params = Lists.newArrayList();
        float pan = PelcodCameraToolkit.getPan();
        float tilt = PelcodCameraToolkit.getTilt();
        params.add(new EquipmentParamsDto("水平角(度)", "pan", String.valueOf(pan), ""));
        params.add(new EquipmentParamsDto("俯仰角(度)", "tilt", String.valueOf(tilt), ""));
        log.info("[pelcod] pan:{} tilt:{}",pan,tilt);
        return params;
    }

    @Override
    public List<EquipmentParamsDto> getDeviceParamsData(QueryParamsDto dto, EquipmentCmdEnum cmdEnum) {
        String pose = paramsCacheTable.get(dto.getIp(), cmdEnum.getDesc());
        if (StrUtil.isNotBlank(pose)){
            try {
                List<EquipmentParamsDto> equipmentParamsDtos = JSONArray.parseArray(pose, EquipmentParamsDto.class);
                if (!equipmentParamsDtos.isEmpty()){
                    return equipmentParamsDtos;
                }
            }catch (Exception e){
                log.error("[hk] parse pose array error {}",e.getMessage());
            }
        }
        List<EquipmentParamsDto> paramsDtos = Lists.newArrayList();
        if (cmdEnum == EquipmentCmdEnum.GET_ORIGIN_PARAMS) {
            paramsDtos.add(CameraParamDTO.createParamsDto("水平角",  "pan", "0.0", ""));
            paramsDtos.add(CameraParamDTO.createParamsDto("俯仰角",  "tilt", "0.0", ""));
        } else if (cmdEnum == EquipmentCmdEnum.GET_BACK_PARAMS_DATA) {
            paramsDtos.add(CameraParamDTO.createParamsDto("水平角",  "pan", "180.0", ""));
            paramsDtos.add(CameraParamDTO.createParamsDto("俯仰角",  "tilt", "0.0", ""));
        }
        return paramsDtos;
    }


    @Override
    public IEquipmentCmdResult executeCmd(QueryParamsDto dto, boolean async, EquipmentCmdEnum cmdEnum, IEquipmentCmdParamsDto cmdParamsDto) {
        if (cmdEnum == EquipmentCmdEnum.PTZ_MOVE) {
            PtzCtrlDTO ptzCtrlDTO = (PtzCtrlDTO) cmdParamsDto;
            PelcodCameraToolkit.ptzCtrl(ptzCtrlDTO);
        }
        return null;
    }

    @Override
    public IEquipmentCmdResult getExecuteCmdResult(EquipmentCmdEnum cmdEnum) {
        return IEquipmentService.super.getExecuteCmdResult(cmdEnum);
    }

    @Override
    public boolean motionAbort(QueryParamsDto dto) {
        //急停以及重置标志位
        PelcodCacheUtil.setStopFlag();
        return true;
    }


    public Table<String, String, String> getParamsCacheTable(){
        return  paramsCacheTable;
    }

}